using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
 
namespace Acms.WebControls
{
    public class AcmsDataList : CompositeDataBoundControl
    {
        public AcmsDataList() : base()
        {
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            Page.RegisterRequiresControlState(this);
        }

        private bool useAjax;
        public bool UseAjax
        {
            get { return useAjax; }
            set { useAjax = value; }
        }
	
        private bool allowPaging;
        public bool AllowPaging
        {
            get { return allowPaging; }
            set { allowPaging = value; }
        }

        private int currentPageIndex;
        public int CurentPageIndex
        {
            get { return currentPageIndex; }
            set 
            {
                if (value < 0)
                {
                    currentPageIndex = 0;
                }
                else
                {
                    currentPageIndex = value;
                }
            }
        }

        private int pageSize = 10;
        public int PageSize
        {
            get { return pageSize; }
            set { pageSize = value; }
        }

        private int pageBlockSize = 10;
        public int PageBlockSize
        {
            get { return pageBlockSize; }
            set { pageBlockSize = value; }
        }

        private int selectedIndex = -1;
        public int SelectedIndex
        {
            get { return selectedIndex; }
            set 
            {
                selectedIndex = value; 
            }
        }

        private int editItemIndex = -1;
        public int EditItemIndex
        {
            get { return editItemIndex; }
            set { editItemIndex = value; }
        }

        private PagerPosition pagerPosition;
        public PagerPosition PagerPosition
        {
            get { return pagerPosition; }
            set { pagerPosition = value; }
        }

        private int recordsDisplayed = 0;

        private bool totalRecordsSet;
        private int totalRecords;
        public int TotalRecords
        {
            get { return totalRecords; }
            set { totalRecords = value; totalRecordsSet = true; }
        }

        public string DataKeyField
        {
            get 
            {
                if (dataKeyFields != null && dataKeyFields.Length == 1)
                {
                    return dataKeyFields[0];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                if (value != null && !string.IsNullOrEmpty(value))
                {
                    dataKeyFields = new string[] { value };
                }
                else
                {
                    dataKeyFields = null;
                }
            }
        }

        private string[] dataKeyFields;
        public string[] DataKeyFields
        {
            get { return dataKeyFields; }
            set { dataKeyFields = value; }
        }

        private List<DataKey> dataKeys;
        public DataKey[] DataKeys
        {
            get 
            { 
                if(dataKeys != null)
                    return dataKeys.ToArray();
                else
                    return null;
            }
        }

        protected override void PerformDataBinding(IEnumerable data)
        {
            base.PerformDataBinding(data);
        }

        DataSourceSelectArguments dataSelectArguments;

        protected override DataSourceSelectArguments CreateDataSourceSelectArguments()
        {
            dataSelectArguments = base.CreateDataSourceSelectArguments();
            if (AllowPaging && GetData().CanPage && GetData().CanRetrieveTotalRowCount)
            {
                dataSelectArguments.RetrieveTotalRowCount = true;
                dataSelectArguments.MaximumRows = this.PageSize;
                dataSelectArguments.StartRowIndex = this.PageSize * this.CurentPageIndex;
            }
            return dataSelectArguments;
        }

        protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
        {
            IEnumerator data = null;
            if (!dataBinding)
            {
                data = new object[this.recordsDisplayed].GetEnumerator();
            }
            else if (dataSource == null)
            {
                data = new object[0].GetEnumerator();
            }
            else if (!AllowPaging)
            {
                data = dataSource.GetEnumerator();
            }
            else if (IsBoundUsingDataSourceID && dataSelectArguments.RetrieveTotalRowCount)
            {
                if (!totalRecordsSet)
                {
                    totalRecords = dataSelectArguments.TotalRowCount;
                    totalRecordsSet = true;
                }
                data = dataSource.GetEnumerator();
            }
            else if (dataSource is IList)
            {
                IList list = dataSource as IList;
                if (!totalRecordsSet)
                {
                    totalRecords = list.Count;
                    totalRecordsSet = true;
                }
                //check current page
                while(totalRecords < currentPageIndex * pageSize)
                {
                    currentPageIndex--;
                }

                if(totalRecords == 0)
                {
                    data = list.GetEnumerator();
                }
                else if (list.Count <= pageSize)
                {
                    //paged data
                    data = list.GetEnumerator();
                }
                else
                {
                    int itemsToDisplay = totalRecords - (currentPageIndex * pageSize);
                    if (itemsToDisplay > pageSize)
                    {
                        itemsToDisplay = pageSize;
                    }

                    if (itemsToDisplay > list.Count)
                    {
                        itemsToDisplay = list.Count;
                    }

                    ArrayList tmp = new ArrayList();
                    for (int n = 0; n < itemsToDisplay; n++)
                    {
                        tmp.Add(list[currentPageIndex * pageSize + n]);
                        if (currentPageIndex * pageSize + n + 1 >= totalRecords)
                        {
                            break;
                        }
                    }
                    data = tmp.GetEnumerator();
                }
            }   
            else
            {
                throw new NotImplementedException(string.Format("AcmsDataList does not currently work with datasource of '{0}' when paging.", dataSource.GetType()));
            }


            //clear the containers
            items = new List<AcmsDataListItem>();
            if (SeperatorTemplate != null)
            {
                seperators = new List<AcmsDataListItem>();
            }

            int i = 0;
            while (data.MoveNext())
            {
                if (items.Count == 0)
                {
                    CreatePager(PagerPosition.Top);
                    CreateHeader();
                }
                else
                {
                    CreateSeperator(i - 1);
                }
                CreateDataListItem(i);
                if (dataBinding)
                {
                    items[items.Count-1].SetDataSource(data.Current);
                }
                i++;
            }
            if (UseAjax && AllowPaging && PageSize < TotalRecords)
            {
                for (int n = i; n < PageSize; n++)
                {
                    AddItemToControls(null, string.Concat("item", n), itemsUpdateAjax.Contains(n));
                }
            }
            if (items.Count > 0)
            {
                CreateFooter();
                CreatePager(PagerPosition.Bottom);
            }
            else
            {
                CreateNoData();
            }

            OnItemsCreated(EventArgs.Empty);

            if(dataBinding)
            {
                recordsDisplayed = items.Count;
                if (!totalRecordsSet)
                {
                    totalRecords = items.Count;
                }
                if (items.Count > 0)
                {
                    if (DataKeyFields != null && DataKeyField.Length > 0)
                    {
                        dataKeys = new List<DataKey>();
                        foreach (AcmsDataListItem item in items)
                        {
                            dataKeys.Add(new DataKey(EvalDataKeys(item)));
                        }
                    }
                    if (TopPager != null && TopPager.Controls[0] is AcmsPagingControl)
                    {
                        ((AcmsPagingControl)TopPager.Controls[0]).TotalRecords = totalRecords;
                    }
                    if (BottomPager != null && BottomPager.Controls[0] is AcmsPagingControl)
                    {
                        ((AcmsPagingControl)BottomPager.Controls[0]).TotalRecords = totalRecords;
                    }

                    DataBindItem(Header);
                    for (i = 0; i < items.Count; i++)
                    {
                        if (i > 0 && Seperators != null)
                        {
                            DataBindItem(Seperators[i - 1]);
                        }
                        DataBindItem(items[i]);
                    }
                    DataBindItem(Footer);

                    DataBindItem(TopPager);
                    DataBindItem(BottomPager);
                }
                else
                {
                    DataBindItem(NoData);
                }
            }
            return items.Count;
        }

        private System.Collections.Specialized.OrderedDictionary EvalDataKeys(AcmsDataListItem item)
        {
            System.Collections.Specialized.OrderedDictionary tmp = new System.Collections.Specialized.OrderedDictionary();
            foreach (string key in DataKeyFields)
            {
                tmp.Add(key, DataBinder.Eval(item.DataItem, key));
            }
            return tmp;
        }

        private void DataBindItem(AcmsDataListItem item)
        {
            if (item != null)
            {
                if (item.IsPager && item.Controls[0] is AcmsPagingControl)
                {
                    AcmsPagingControl pager = (AcmsPagingControl)item.Controls[0];
                    pager.CurrentPageIndex = this.CurentPageIndex;
                    pager.TotalRecords = this.TotalRecords;
                    pager.PageSize = PageSize;
                    pager.BlockSize = PageBlockSize;
                }
                item.DataBind();
                OnItemDataBound(new AcmsDataListItemEventArgs(item));
                if(item.AjaxPanel != null)
                {
                    item.AjaxPanel.Update();
                }
            }
        }

        private void AddItemToControls(AcmsDataListItem item, string id, bool updateAjaxPanel)
        {
            if (item != null)
            {
                item.ID = id;
            }
            if (UseAjax)
            {
                UpdatePanel pnl = new UpdatePanel();
                pnl.ID = string.Concat(id, "Ajax");
                pnl.ContentTemplate = new ItemTemplate(item);
                pnl.UpdateMode = UpdatePanelUpdateMode.Conditional;
                this.Controls.Add(pnl);
                if (updateAjaxPanel)
                {
                    pnl.Update();
                }
            }
            else if(item != null)
            {
                this.Controls.Add(item);
            }
        }

        private void CreateNoData()
        {
            if (noDataTemplate != null)
            {
                noData = Acms.WebControls.AcmsDataListItem.CreateNoData();
                AddItemToControls(noData, "noData", noDataUpdateAjax);
                noData.ApplyStyle(noDataStyle);
                NoDataTemplate.InstantiateIn(noData);
                OnItemCreated(new AcmsDataListItemEventArgs(noData));
            }
        }

        private void CreateHeader()
        {
            if (HeaderTemplate != null)
            {
                header = AcmsDataListItem.CreateHeader();
                AddItemToControls(header, "header", headerUpdateAjax);
                header.ApplyStyle(headerStyle);
                HeaderTemplate.InstantiateIn(header);
                OnItemCreated(new AcmsDataListItemEventArgs(header));
            }
        }

        private void CreateFooter()
        {
            if (FooterTemplate != null)
            {
                footer = AcmsDataListItem.CreateFooter();
                AddItemToControls(footer, "footer", footerUpdateAjax);
                footer.ApplyStyle(footerStyle);
                FooterTemplate.InstantiateIn(footer);
                OnItemCreated(new AcmsDataListItemEventArgs(footer));
            }
        }
        
        private void CreateSeperator(int i)
        {
            if (SeperatorTemplate != null)
            {
                AcmsDataListItem seperator = AcmsDataListItem.CreateSeperator(i);
                seperators.Add(seperator);
                AddItemToControls(seperator, string.Concat("seperator", i), seperatorsUpdateAjax.Contains(i));
                seperator.ApplyStyle(seperatorStyle);
                SeperatorTemplate.InstantiateIn(seperator);
                OnItemCreated(new AcmsDataListItemEventArgs(seperator));
            }
        }

        private void CreateDataListItem(int i)
        {
            //CreateItem and Choose Template
            AcmsDataListItem item = null;
            ITemplate templateToUse = null;
            if(i == editItemIndex)
            {
                item = AcmsDataListItem.CreateEditItem(i);
                if(EditItemTemplate != null)
                {
                    templateToUse = EditItemTemplate;
                }
                else if(item.IsAlternateItem && AlternatingItemTemplate != null)
                {
                    templateToUse = AlternatingItemTemplate;
                }
                else
                {
                    templateToUse = ItemTemplate;
                }
            }
            else if(i == selectedIndex)
            {
                item = AcmsDataListItem.CreateSelectedItem(i);
                if(SelectedItemTemplate != null)
                {
                    templateToUse = SelectedItemTemplate;
                }
                else if(item.IsAlternateItem && AlternatingItemTemplate != null)
                {
                    templateToUse = AlternatingItemTemplate;
                }
                else
                {
                    templateToUse = ItemTemplate;
                }
            }
            else
            {
                item = AcmsDataListItem.CreateItem(i);
                if(item.IsAlternateItem && AlternatingItemTemplate != null)
                {
                    templateToUse = AlternatingItemTemplate;
                }
                else
                {
                    templateToUse = ItemTemplate;
                }
            }

            items.Add(item);
            AddItemToControls(item, string.Concat("item", i), itemsUpdateAjax.Contains(i));
            if (item.IsSelectedItem && SelectedItemStyle != null)
            {
                item.ApplyStyle(SelectedItemStyle);
            }
            else if ((item.IsSelectedItem || item.IsAlternateItem) && AlternatingItemStyle != null)
            {
                item.ApplyStyle(AlternatingItemStyle);
            }
            else
            {
                item.ApplyStyle(ItemStyle);
            }
            templateToUse.InstantiateIn(item);
            OnItemCreated(new AcmsDataListItemEventArgs(item));
        }

        private void CreatePager(PagerPosition position)
        {
            if (AllowPaging && (PagerPosition == PagerPosition.TopAndBottom || PagerPosition == position))
            {
                AcmsPagingControl pager = new AcmsPagingControl();
                pager.ID = "pager";
                pager.UseAjax = this.UseAjax;
                AcmsDataListItem item = null;
                string id;
                if (position == PagerPosition.Top)
                {
                    topPager = AcmsDataListItem.CreatePager(true);
                    id = "topPager";
                    item = topPager;
                    if (TopPagerStyle != null)
                    {
                        topPager.ApplyStyle(TopPagerStyle);
                    }
                }
                else
                {
                    bottomPager = AcmsDataListItem.CreatePager(false);
                    id = "bottomPager";
                    item = bottomPager;
                    if (BottomPagerStyle != null)
                    {
                        bottomPager.ApplyStyle(BottomPagerStyle);
                    }
                }
                item.Controls.Add(pager);
                AddItemToControls(item, id, pagerUpdateAjax);
                OnItemCreated(new AcmsDataListItemEventArgs(item));
            }
        }

        private void OnItemCreated(AcmsDataListItemEventArgs e)
        {
            if (ItemCreated != null)
            {
                ItemCreated(this, e);
            }
        }

        private void OnItemsCreated(EventArgs e)
        {
            if (ItemsCreated != null)
            {
                ItemsCreated(this, e);
            }
        }

        private void OnItemDataBound(AcmsDataListItemEventArgs e)
        {
            if (ItemDataBound != null)
            {
                ItemDataBound(this, e);
            }
        }

        #region Templates
        private bool noDataUpdateAjax;
        private AcmsDataListItem noData;
        public AcmsDataListItem NoData
        {
            get { return noData; }
        }

        private System.Web.UI.ITemplate noDataTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The no data template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate NoDataTemplate
        {
            get { return noDataTemplate; }
            set { noDataTemplate = value; }
        }

        private Style noDataStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style NoDataStyle
        {
            get { return noDataStyle; }
            set { noDataStyle = value; }
        }

        private bool pagerUpdateAjax;

        private Style topPagerStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style TopPagerStyle
        {
            get { return topPagerStyle; }
            set { topPagerStyle = value; }
        }

        private AcmsDataListItem topPager;
        public AcmsDataListItem TopPager
        {
            get { return topPager; }
        }

        private Style bottomPagerStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style BottomPagerStyle
        {
            get { return bottomPagerStyle; }
            set { bottomPagerStyle = value; }
        }

        private AcmsDataListItem bottomPager;
        public AcmsDataListItem BottomPager
        {
            get { return bottomPager; }
        }

        private bool headerUpdateAjax;
        private AcmsDataListItem header;
        public AcmsDataListItem Header
        {
            get { return header; }
        }

        private System.Web.UI.ITemplate headerTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The header template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate HeaderTemplate
        {
            get { return headerTemplate; }
            set { headerTemplate = value; }
        }

        private Style headerStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style HeaderStyle
        {
            get { return headerStyle; }
            set { headerStyle = value; }
        }

        private bool footerUpdateAjax;
        private AcmsDataListItem footer;
        public AcmsDataListItem Footer
        {
            get { return footer; }
        }

        private System.Web.UI.ITemplate footerTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The header template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate FooterTemplate
        {
            get { return footerTemplate; }
            set { footerTemplate = value; }
        }

        private Style footerStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style FooterStyle
        {
            get { return footerStyle; }
            set { footerStyle = value; }
        }

        private List<int> seperatorsUpdateAjax = new List<int>();
        private List<AcmsDataListItem> seperators;
        public AcmsDataListItem[] Seperators
        {
            get 
            {
                if (seperators == null)
                    return null;
                else
                    return seperators.ToArray();
            }
        }

        private System.Web.UI.ITemplate seperatorTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The header template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate SeperatorTemplate
        {
            get { return seperatorTemplate; }
            set { seperatorTemplate = value; }
        }

        private Style seperatorStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style SeperatorStyle
        {
            get { return seperatorStyle; }
            set { seperatorStyle = value; }
        }

        private List<int> itemsUpdateAjax = new List<int>();
        private List<AcmsDataListItem> items;
        public AcmsDataListItem[] Items
        {
            get
            {
                if (items == null)
                    return null;
                else
                    return items.ToArray();
            }
        }

        private System.Web.UI.ITemplate itemTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The item template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate ItemTemplate
        {
            get { return itemTemplate; }
            set { itemTemplate = value; }
        }

        private Style itemStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style ItemStyle
        {
            get { return itemStyle; }
            set { itemStyle = value; }
        }
        
        private System.Web.UI.ITemplate alternatingItemTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The alternating template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate AlternatingItemTemplate
        {
            get { return alternatingItemTemplate; }
            set { alternatingItemTemplate = value; }
        }

        private Style alternatingItemStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style AlternatingItemStyle
        {
            get { return alternatingItemStyle; }
            set { alternatingItemStyle = value; }
        }

        private System.Web.UI.ITemplate selectedItemTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The seleected template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate SelectedItemTemplate
        {
            get { return selectedItemTemplate; }
            set { selectedItemTemplate = value; }
        }

        private Style selectedItemStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style SelectedItemStyle
        {
            get { return selectedItemStyle; }
            set { selectedItemStyle = value; }
        }

        private System.Web.UI.ITemplate editItemTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The edit template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate EditItemTemplate
        {
            get { return editItemTemplate; }
            set { editItemTemplate = value; }
        }

        private Style editItemStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style EditItemtyle
        {
            get { return editItemStyle; }
            set { editItemStyle = value; }
        }

        private System.Web.UI.ITemplate insertItemTemplate;
        [
        Browsable(false),
        DefaultValue(null),
        Description("The insert template."),
        TemplateContainer(typeof(AcmsDataListItem)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public System.Web.UI.ITemplate InsertItemTemplate
        {
            get { return insertItemTemplate; }
            set { insertItemTemplate = value; }
        }

        private Style insertItemStyle;
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public Style InsertItemStyle
        {
            get { return insertItemStyle; }
            set { insertItemStyle = value; }
        }
        #endregion

        private void OnSelectedIndexChanged(IndexChangedEventArgs e)
        {
            itemsUpdateAjax.Add(e.PreviousIndex);
            if (SelectedIndexChanged != null)
            {
                SelectedIndexChanged(this, e);
            }
            RequiresDataBinding = true;
        }

        private void OnPageIndexChanged(IndexChangedEventArgs e)
        {
            for (int i = 0; i < PageSize; i++)
            {
                itemsUpdateAjax.Add(i);
            }
            if (PageIndexChanged != null)
            {
                PageIndexChanged(this, e);
            }
            RequiresDataBinding = true;
        }

        #region events
        protected void OnItemCommand(AcmsDataListItemCommandEventArgs e)
        {
            if (ItemCommand != null)
            {
                ItemCommand(this, e);
            }
        }

        public event EventHandler<AcmsDataListItemCommandEventArgs> ItemCommand;
        public event EventHandler<IndexChangedEventArgs> SelectedIndexChanged;
        public event EventHandler<IndexChangedEventArgs> PageIndexChanged;
        public event EventHandler<AcmsDataListItemEventArgs> ItemCreated;
        public event EventHandler ItemsCreated;
        public event EventHandler<AcmsDataListItemEventArgs> ItemDataBound;
        #endregion

        protected override bool OnBubbleEvent(object source, EventArgs args)
        {
            if (args is AcmsDataListItemCommandEventArgs)
            {
                AcmsDataListItemCommandEventArgs tmp = (AcmsDataListItemCommandEventArgs)args;
                if (tmp.CommandName == "Select")
                {
                    if (tmp.Item.ItemIndex != selectedIndex)
                    {
                        int prev = selectedIndex;
                        selectedIndex = tmp.Item.ItemIndex;
                        OnSelectedIndexChanged(new IndexChangedEventArgs(selectedIndex, prev));
                    }
                    return true;
                }
                else if (tmp.CommandName == "Pager")
                {
                    int prev = currentPageIndex;
                    currentPageIndex = (int)tmp.CommandArgument;
                    OnPageIndexChanged(new IndexChangedEventArgs(currentPageIndex, prev));
                    return true;
                }
                else
                {
                    OnItemCommand(tmp);
                    return true;
                }
            }
            else
            {
                return false;
            }
        }

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }
        protected override void OnPreRender(EventArgs e)
        {
            Page.ClientScript.RegisterExpandoAttribute(this.ClientID, "items", this.items.Count.ToString());
            Page.ClientScript.RegisterExpandoAttribute(this.ClientID, "selectedIndex", this.SelectedIndex.ToString());
            base.OnPreRender(e);
        }
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);
        }

        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            if (ViewState["TotalRecords"] is int)
            {
                totalRecords = (int)ViewState["TotalRecords"];
            }
            if (ViewState["RecordsDisplayed"] is int)
            {
                recordsDisplayed = (int)ViewState["RecordsDisplayed"];
            }
            if (ViewState["SelectedIndex"] is int)
            {
                selectedIndex = (int)ViewState["SelectedIndex"];
            }
            if (ViewState["EditItemIndex"] is int)
            {
                editItemIndex = (int)ViewState["EditItemIndex"];
            }
            if (ViewState["CurrentPageIndex"] is int)
            {
                currentPageIndex = (int)ViewState["CurrentPageIndex"];
            }

        }

        protected override object SaveViewState()
        {
            ViewState["RecordsDisplayed"] = recordsDisplayed;
            ViewState["TotalRecords"] = totalRecords;
            ViewState["SelectedIndex"] = selectedIndex;
            ViewState["EditItemIndex"] = editItemIndex;
            ViewState["CurrentPageIndex"] = currentPageIndex;
            return base.SaveViewState();
        }

        protected override object SaveControlState()
        {
            object tmp = base.SaveControlState();
            if (dataKeys != null)
            {
                if (tmp != null)
                {
                    return new Pair(tmp, SaveDataKeysToControlState());
                }
                else
                {
                    return SaveDataKeysToControlState();
                }
            }
            else
            {
                return tmp;
            }
        }

        protected override void LoadControlState(object savedState)
        {
            if (savedState != null)
            {
                Pair p = savedState as Pair;
                if (p != null)
                {
                    base.LoadControlState(p.First);
                    LoadKeysFromControlState(p.Second as System.Collections.Specialized.OrderedDictionary[]);
                }
                else
                {
                    LoadKeysFromControlState(savedState as System.Collections.Specialized.OrderedDictionary[]);
                }
            }
        }

        private System.Collections.Specialized.OrderedDictionary[] SaveDataKeysToControlState()
        {
            List<System.Collections.Specialized.OrderedDictionary> tmp = new List<System.Collections.Specialized.OrderedDictionary>();
            foreach (DataKey key in DataKeys)
            {
                tmp.Add((System.Collections.Specialized.OrderedDictionary)key.Values);
            }
            return tmp.ToArray();
        }
        
        private void LoadKeysFromControlState(System.Collections.Specialized.OrderedDictionary[] values)
        {
            if (values != null)
            {
                dataKeys = new List<DataKey>();
                foreach (System.Collections.Specialized.OrderedDictionary tmp in values)
                {
                    dataKeys.Add(new DataKey(tmp));
                }
            }
        }
    }

    public class ItemTemplate : ITemplate
    {
        public ItemTemplate(AcmsDataListItem item)
        {
            this.item = item;
        }

        private AcmsDataListItem item;



        #region ITemplate Members

        public void InstantiateIn(Control container)
        {
            if (item != null)
            {
                container.Controls.Add(item);
            }
        }

        #endregion
    }

}
